## Reads in AOI position text files from Toii
## Will return tibble of columns sec, x, y, with rows for each timestamp/AOI position
get_xy_timestamp <- function(z){
x <- read_lines(z) %>%
as_tibble() %>%
rowid_to_column("ID")
# pull out timestamp rows
timestamps <- x %>%
filter(str_detect(value, "timestamp")) %>%
separate(value, into = c("throw","timestamp"), sep = " = ") %>%
separate(timestamp, into = c("one","two","sec"), sep = ":") %>%
select(sec) %>%
mutate(sec = as.numeric(sec))
# Find AOI coordinate rows
xys <- x %>%
mutate(find = str_detect(value, "X\tY"))
# first vertex (2 rows after each "XY" line)
xys_row <- which(xys$find) + 2
xy1 <- x %>%
filter(ID %in% xys_row) %>%
separate(value, into = c("x1","y1"), sep = "\t") %>%
select(-ID)
# opposite vertex (2 more rows down)
xys_row <- xys_row + 2
xy2 <- x %>%
filter(ID %in% xys_row) %>%
separate(value, into = c("x2","y2"), sep = "\t") %>%
select(-ID)
# Now get average XY position per timestamp
xys <- cbind(timestamps, xy1, xy2) %>%
mutate_all(as.numeric) %>%
rowwise() %>%
mutate(x = mean(x1,x2),
y = mean(y1, y2)) %>%
select(sec, x, y)
}
Let’s give this a shot!!
Three Bears Forward
First let’s see who’s in our dataset. This is Test 1 - 3 Bears - Forward. We’re pulling cleaned-up names and assigned groups from our final dataset that we used in our AOI analysis. Then we are removing participants whose Three Bears Forward story wasn’t included in our AOI analysis due to <25% looking time or other reasons.
library(tidyverse)
library(openxlsx)
library(janitor)
# Get Three Bears data
data <- read.xlsx("Test1_Cindy_bears_FW_Examine for Spatial Referencing.xlsx") %>%
clean_names() %>%
rename(y = gaze_point_y_mc_spx,
language = language_value,
name = participant_name,
group = group_value)
# Pull clean names and join to data (and add Laura2 for Laura (missing stories))
cleannames <- read_csv("partnames.csv") %>%
distinct() %>%
rename(name = participant) %>%
filter(name != "Laura2")
data <- data %>%
left_join(cleannames, by = "name") %>%
select(-name) %>%
rename(name = new_participant) %>%
filter(!is.na(name))
# Pull final group assignments and join to data
cleangroups <- read_csv("finaldataset.csv") %>%
select(participant, maingroup) %>%
rename(name = participant) %>%
distinct()
data <- data %>% left_join(cleangroups, by = "name") %>%
select(-group)
# Let's find out who was NOT included in Three Bears
excluded <- read_csv("finaldataset.csv") %>%
select(participant, maingroup, story, direction, eye_exclude) %>%
filter(story == "Goldilocks" & direction == "forward") %>%
rename(name = participant) %>%
select(name, eye_exclude)
data <- data %>% left_join(excluded, by = "name") %>%
filter(!eye_exclude) %>%
filter(!is.na(eye_exclude))
data %>% select(name, maingroup) %>% distinct()
Now let’s graph!!
Messy, I know, but already we can see some HearingNovice has big shifts downward. And some HearingLate too.

Group Averages
Next, let’s make group averages.
averaged_y <- data %>%
group_by(maingroup, gaze_point_index) %>%
summarise(y_mean = mean(y, na.rm = T),
y_sd = sd(y, na.rm = T),
y_count = n(),
y_se = y_sd/sqrt(y_count))
averaged_y %>%
ggplot() +
geom_line(aes(x = gaze_point_index, y = y_mean, color = maingroup)) +
geom_ribbon(aes(x = gaze_point_index,
ymin = y_mean-y_se,
ymax = y_mean+y_se,
fill = maingroup), alpha = 0.5) +
scale_y_reverse(limits = c(1200,0)) +
theme_bw() +
facet_wrap("maingroup")


Group Averages With Smoothing
So I’ll back up and smooth each person’s data using a moving average window of span = 5. Taken from our adult manuscript which had this:
The data were then smoothed with a standard moving average noise reduction algorithm (window size = 5 samples) which acts as a low-pass filter that reduces the influence of microsaccades, blinks, and large data gaps (based on Yarbus, 1967).
The below chart shows Adam’s data, blue is unsmoothed and red is smoothed.
data <- data %>%
group_by(maingroup, recording_name) %>%
mutate(y_ma = RcppRoll::roll_mean(y, n = 5, fill = 0))
data %>%
filter(recording_name == "Adam_Good") %>%
ggplot() +
geom_line(aes(x = gaze_point_index, y = y), color = "blue", alpha = 0.25, size = 0.5) +
geom_line(aes(x = gaze_point_index, y = y_ma), color = "red", size = 0.2) +
scale_y_reverse(limits = c(475, 325)) +
theme_bw()

So that’s nice. Let’s go do group averages again.
averaged_y <- data %>%
group_by(maingroup, gaze_point_index) %>%
summarise(y_mean = mean(y_ma, na.rm = T),
y_sd = sd(y_ma, na.rm = T),
y_count = n(),
y_se = y_sd/sqrt(y_count))
averaged_y %>%
ggplot() +
geom_line(aes(x = gaze_point_index, y = y_mean, color = maingroup)) +
geom_ribbon(aes(x = gaze_point_index,
ymin = y_mean-y_se,
ymax = y_mean+y_se,
fill = maingroup), alpha = 0.5) +
scale_y_reverse(limits = c(1200,0)) +
theme_bw() +
facet_wrap("maingroup")



Group Averages With More Smoothing
Maybe we should smooth even more. Sample size = 10!
data <- data %>%
group_by(maingroup, recording_name) %>%
mutate(y_ma2 = RcppRoll::roll_mean(y, n = 10, fill = 0))
# data %>%
# filter(recording_name == "Adam_Good") %>%
# ggplot() +
# geom_line(aes(x = gaze_point_index, y = y), color = "blue", alpha = 0.25, size = 0.5) +
# geom_line(aes(x = gaze_point_index, y = y_ma2), color = "red", size = 0.2) +
# scale_y_reverse(limits = c(475, 325)) +
# theme_bw()
averaged_y <- data %>%
group_by(maingroup, gaze_point_index) %>%
summarise(y_mean = mean(y_ma2, na.rm = T),
y_sd = sd(y_ma2, na.rm = T),
y_count = n(),
y_se = y_sd/sqrt(y_count))
write_csv(averaged_y, "bears_time_series_group_averages.csv")
library(hrbrthemes)
Registered S3 methods overwritten by 'htmltools':
method from
print.html tools:rstudio
print.shiny.tag tools:rstudio
print.shiny.tag.list tools:rstudio
averaged_y %>%
ggplot() +
geom_line(aes(x = gaze_point_index, y = y_mean, color = maingroup), size = 0.8) +
geom_ribbon(aes(x = gaze_point_index,
ymin = y_mean-y_se,
ymax = y_mean+y_se,
fill = maingroup), alpha = 0.5) +
scale_y_reverse(limits = c(1200,0)) +
facet_wrap("maingroup") +
labs(x = "time (ms)", y = "pixels", title = "Figure 1. Vertical Eye Gaze Position Across One ASL Narrative") +
guides(color = F, fill = F) +
theme_ipsum_rc()


averaged_y %>%
filter(maingroup == "DeafEarly" | maingroup == "HearingNovice") %>%
ggplot() +
geom_line(aes(x = gaze_point_index, y = y_mean, color = maingroup), size = 0.8) +
geom_ribbon(aes(x = gaze_point_index,
ymin = y_mean-y_se,
ymax = y_mean+y_se,
fill = maingroup), alpha = 0.1) +
scale_y_reverse(limits = c(700,300)) +
labs(x = "time (ms)", y = "pixels", title = "Figure 2. Deaf Early Signers vs. Hearing Novice Signers", color = "", fill = "") +
theme_ipsum_rc()

Everything Else That Was Already Here
Next let’s plot the moments where spatial referencing happens. Those are frames
- 198 to 223
- 265 to 288
- 352 to 380
The max gazepointindex is around 2580. At 120 Hz, that’s 21.5 seconds which is just right, that’s the length. Let’s go ahead and convert gazepointindex to seconds.
So we just have to convert frames to gazepointindex. The video is a total of 536 frames, at 25 FPS that’s 21.5 seconds. 535/25 = 21.5, so we divide all those frames by 25.
- 7.92s to 8.92s
- 10.6s to 11.52s
- 14.08s to 15.2s
And plot those!
data <- data %>%
rowwise() %>%
mutate(secs = gaze_point_index/120)
data %>%
ggplot(aes(x = secs, y = y, color = maingroup, group = name)) +
scale_y_reverse() +
geom_line() +
annotate("rect", xmin = 7.92, xmax = 8.92, ymin = 0, ymax = 900,
alpha = .2, fill = "red") +
annotate("rect", xmin = 10.6, xmax = 11.52, ymin = 0, ymax = 900,
alpha = .2, fill = "red") +
annotate("rect", xmin = 14.08, xmax = 15.2, ymin = 0, ymax = 900,
alpha = .2, fill = "red") +
theme_bw()

Maybe easier if we separate groups of signers.
data %>%
ggplot(aes(x = secs, y = y, color = maingroup, group = name)) +
scale_y_reverse() +
geom_line(alpha = 0.5) +
annotate("rect", xmin = 7.92, xmax = 8.92, ymin = 0, ymax = 900,
alpha = .2, fill = "red") +
annotate("rect", xmin = 10.6, xmax = 11.52, ymin = 0, ymax = 900,
alpha = .2, fill = "red") +
annotate("rect", xmin = 14.08, xmax = 15.2, ymin = 0, ymax = 900,
alpha = .2, fill = "red") +
facet_grid(maingroup ~ .) +
theme_bw() +
guides(color = FALSE)

Next, we’re going to add AOI position information. We’re going to pull in information on signers’ right hand position (and then apply the same idea to other body parts). I successfully wrote a function called get_xy_timestamp to do this! Yay. I’m chuffed, as the British would say.
Let’s try this on Stephanie’s data. Let’s see if we can find a correlation between any of those and the eye gaze y-position.
Error: 'aoi_position/Cindy_bears_FW_Position of Right Hand.txt' does not exist in current working directory ('/Users/adamstone/Dropbox/_UCSD/Data Analysis/Study1AdultsNew').
Now let’s work on correlations. First, our AOI vectors are not the same size as our eye gaze vectors, and the x/y position is irregularly spaced across time (irregularly spaced key frames).
Joining, by = "sec"
[1] 0.2894728

Let’s separate out individual signers.
make_signer_plots <- function(groupname, line_color) {
data %>%
filter(maingroup == groupname) %>%
ggplot(aes(x = secs, y = y)) +
scale_y_reverse() +
geom_line(alpha = 1, color = line_color) +
annotate("rect", xmin = 7.92, xmax = 8.92, ymin = 0, ymax = 900,
alpha = .2, fill = "red") +
annotate("rect", xmin = 10.6, xmax = 11.52, ymin = 0, ymax = 900,
alpha = .2, fill = "red") +
annotate("rect", xmin = 14.08, xmax = 15.2, ymin = 0, ymax = 900,
alpha = .2, fill = "red") +
geom_step(data = rhand, aes(x = sec, y = y), color = "red", linetype = "longdash", alpha = 0.5) +
geom_step(data = lhand, aes(x = sec, y = y), color = "blue", linetype = "longdash", alpha = 0.5) +
geom_step(data = mouth, aes(x = sec, y = y), color = "black", linetype = "longdash", alpha = 0.5) +
annotate("text", label = "Right Hand", x = 3, y = 1000, color = "red", alpha = 0.5) +
annotate("text", label = "Left Hand", x = 3, y = 1100, color = "blue", alpha = 0.5) +
annotate("text", label = "Mouth", x = 3, y = 200, color = "black", alpha = 0.5) +
facet_grid(name ~ .) +
ggtitle(groupname) +
theme_bw()
}
make_signer_plots("DeafEarly", "red")




Okay so with Early ASL obviously very steady gaze. NoviceASL has lot of downshifts. Some align with spatial referencing, some do not. We need more of them (let’s look at other stories w better data).
Midas Forward
# Get Midas data
data <- read_csv("../Adult Data/rawdata/midasfw.csv") %>%
clean_names() %>%
rename(y = gaze_point_y_mc_spx,
language = language_value,
name = participant_name,
group = group_value)
# Pull clean names and join to data
cleannames <- read_csv("partnames.csv") %>%
distinct() %>%
rename(name = participant)
data <- data %>% left_join(cleannames, by = "name") %>%
select(-name) %>%
rename(name = new_participant) %>%
filter(!is.na(name))
# Pull final group assignments and join to data
cleangroups <- read_csv("finaldataset.csv") %>%
select(participant, maingroup) %>%
rename(name = participant) %>%
distinct()
data <- data %>% left_join(cleangroups, by = "name") %>%
select(-group)
# Let's find out who was NOT included in Three Bears
excluded <- read_csv("finaldataset.csv") %>%
select(participant, maingroup, story, direction, eye_exclude) %>%
filter(story == "KingMidas" & direction == "forward") %>%
rename(name = participant) %>%
select(name, eye_exclude)
data <- data %>% left_join(excluded, by = "name") %>%
filter(!eye_exclude) %>%
filter(!is.na(eye_exclude))
data %>% select(name, maingroup) %>% distinct()
Now let’s graph!!
Hm. One person seems wrong.

Okay it’s Jesse’s data that seems off. We’ll remove him for now and come back to it, figure out why.

Next let’s plot the moments where spatial referencing happens. Those are frames
- 248 to 427
- 460 to 508
- 512 to 560
Like before, we’ll convert gazepointindex to seconds (by dividing 120) and all frames to seconds (by dividing 25).
- 9.92s to 17.08s
- 18.4s to 20.32s
- 20.48s to 22.4s
data <- data %>%
rowwise() %>%
mutate(secs = gaze_point_index/120)
data %>%
ggplot(aes(x = secs, y = y, color = maingroup, group = name)) +
scale_y_reverse() +
scale_x_continuous(limits = c(0, 37.5)) +
geom_line() +
annotate("rect", xmin = 9.92, xmax = 17.08, ymin = 0, ymax = 900,
alpha = .2, fill = "red") +
annotate("rect", xmin = 18.4, xmax = 20.32, ymin = 0, ymax = 900,
alpha = .2, fill = "red") +
annotate("rect", xmin = 20.48, xmax = 22.4, ymin = 0, ymax = 900,
alpha = .2, fill = "red")

Maybe easier if we separate groups of signers.
data %>%
ggplot(aes(x = secs, y = y, color = maingroup, group = name)) +
scale_y_reverse() +
scale_x_continuous(limits = c(0, 37.5)) +
geom_line(alpha = 0.5) +
annotate("rect", xmin = 9.92, xmax = 17.08, ymin = 0, ymax = 900,
alpha = .2, fill = "red") +
annotate("rect", xmin = 18.4, xmax = 20.32, ymin = 0, ymax = 900,
alpha = .2, fill = "red") +
annotate("rect", xmin = 20.48, xmax = 22.4, ymin = 0, ymax = 900,
alpha = .2, fill = "red") +
facet_grid(maingroup ~ .)

Individual signers.
data %>%
filter(maingroup == "DeafEarly") %>%
ggplot(aes(x = secs, y = y, group = name)) +
scale_x_continuous(limits = c(0, 37.5)) +
scale_y_reverse() +
geom_line(alpha = 1, color = "red") +
annotate("rect", xmin = 9.92, xmax = 17.08, ymin = 0, ymax = 900,
alpha = .2, fill = "red") +
annotate("rect", xmin = 18.4, xmax = 20.32, ymin = 0, ymax = 900,
alpha = .2, fill = "red") +
annotate("rect", xmin = 20.48, xmax = 22.4, ymin = 0, ymax = 900,
alpha = .2, fill = "red") +
facet_grid(name ~ .) +
ggtitle("DeafEarly")

data %>%
filter(maingroup == "DeafLate") %>%
ggplot(aes(x = secs, y = y, group = name)) +
scale_y_reverse() +
scale_x_continuous(limits = c(0, 37.5)) +
geom_line(alpha = 1, color = "dark green") +
annotate("rect", xmin = 9.92, xmax = 17.08, ymin = 0, ymax = 900,
alpha = .2, fill = "red") +
annotate("rect", xmin = 18.4, xmax = 20.32, ymin = 0, ymax = 900,
alpha = .2, fill = "red") +
annotate("rect", xmin = 20.48, xmax = 22.4, ymin = 0, ymax = 900,
alpha = .2, fill = "red") +
facet_grid(name ~ .) +
ggtitle("DeafLate")

data %>%
filter(maingroup == "HearingLate") %>%
ggplot(aes(x = secs, y = y, group = name)) +
scale_y_reverse() +
scale_x_continuous(limits = c(0, 37.5)) +
geom_line(alpha = 1, color = "blue") +
annotate("rect", xmin = 9.92, xmax = 17.08, ymin = 0, ymax = 900,
alpha = .2, fill = "red") +
annotate("rect", xmin = 18.4, xmax = 20.32, ymin = 0, ymax = 900,
alpha = .2, fill = "red") +
annotate("rect", xmin = 20.48, xmax = 22.4, ymin = 0, ymax = 900,
alpha = .2, fill = "red") +
facet_grid(name ~ .) +
ggtitle("HearingLate")

data %>%
filter(maingroup == "HearingNovice") %>%
ggplot(aes(x = secs, y = y, group = name)) +
scale_y_reverse() +
scale_x_continuous(limits = c(0, 37.5)) +
geom_line(alpha = 1, color = "purple") +
annotate("rect", xmin = 9.92, xmax = 17.08, ymin = 0, ymax = 900,
alpha = .2, fill = "red") +
annotate("rect", xmin = 18.4, xmax = 20.32, ymin = 0, ymax = 900,
alpha = .2, fill = "red") +
annotate("rect", xmin = 20.48, xmax = 22.4, ymin = 0, ymax = 900,
alpha = .2, fill = "red") +
facet_grid(name ~ .) +
ggtitle("HearingNovice")

LS0tCnRpdGxlOiAiU3BhdGlhbCBSZWZlcmVuY2luZyIKYXV0aG9yOiAiQWRhbSBTdG9uZSwgUGhEIgpkYXRlOiAnYHIgZm9ybWF0KFN5cy5EYXRlKCksICIlbS0lZC0lWSIpYCcKb3V0cHV0OgogIGh0bWxfbm90ZWJvb2s6CiAgICBjb2RlX2ZvbGRpbmc6IGhpZGUKICAgIGhpZ2hsaWdodDogdGFuZ28KICAgIHRoZW1lOiBwYXBlcgogICAgdG9jOiB5ZXMKICAgIHRvY19kZXB0aDogMgogICAgdG9jX2Zsb2F0OiB5ZXMKLS0tCgpgYGB7cn0KIyMgUmVhZHMgaW4gQU9JIHBvc2l0aW9uIHRleHQgZmlsZXMgZnJvbSBUb2lpCiMjIFdpbGwgcmV0dXJuIHRpYmJsZSBvZiBjb2x1bW5zIHNlYywgeCwgeSwgd2l0aCByb3dzIGZvciBlYWNoIHRpbWVzdGFtcC9BT0kgcG9zaXRpb24KCmdldF94eV90aW1lc3RhbXAgPC0gZnVuY3Rpb24oeil7Cgp4IDwtIHJlYWRfbGluZXMoeikgJT4lCiAgYXNfdGliYmxlKCkgJT4lCiAgcm93aWRfdG9fY29sdW1uKCJJRCIpCgojIHB1bGwgb3V0IHRpbWVzdGFtcCByb3dzCnRpbWVzdGFtcHMgPC0geCAlPiUKICBmaWx0ZXIoc3RyX2RldGVjdCh2YWx1ZSwgInRpbWVzdGFtcCIpKSAlPiUKICBzZXBhcmF0ZSh2YWx1ZSwgaW50byA9IGMoInRocm93IiwidGltZXN0YW1wIiksIHNlcCA9ICIgPSAiKSAlPiUKICBzZXBhcmF0ZSh0aW1lc3RhbXAsIGludG8gPSBjKCJvbmUiLCJ0d28iLCJzZWMiKSwgc2VwID0gIjoiKSAlPiUKICBzZWxlY3Qoc2VjKSAlPiUKICBtdXRhdGUoc2VjID0gYXMubnVtZXJpYyhzZWMpKQoKIyBGaW5kIEFPSSBjb29yZGluYXRlIHJvd3MKeHlzIDwtIHggJT4lCiAgbXV0YXRlKGZpbmQgPSBzdHJfZGV0ZWN0KHZhbHVlLCAiWFx0WSIpKQoKIyBmaXJzdCB2ZXJ0ZXggKDIgcm93cyBhZnRlciBlYWNoICJYWSIgbGluZSkKeHlzX3JvdyA8LSB3aGljaCh4eXMkZmluZCkgKyAyCgp4eTEgPC0geCAlPiUKICBmaWx0ZXIoSUQgJWluJSB4eXNfcm93KSAlPiUKICBzZXBhcmF0ZSh2YWx1ZSwgaW50byA9IGMoIngxIiwieTEiKSwgc2VwID0gIlx0IikgJT4lCiAgc2VsZWN0KC1JRCkKCiMgb3Bwb3NpdGUgdmVydGV4ICgyIG1vcmUgcm93cyBkb3duKQp4eXNfcm93IDwtIHh5c19yb3cgKyAyCgp4eTIgPC0geCAlPiUKICBmaWx0ZXIoSUQgJWluJSB4eXNfcm93KSAlPiUKICBzZXBhcmF0ZSh2YWx1ZSwgaW50byA9IGMoIngyIiwieTIiKSwgc2VwID0gIlx0IikgJT4lCiAgc2VsZWN0KC1JRCkKCiMgTm93IGdldCBhdmVyYWdlIFhZIHBvc2l0aW9uIHBlciB0aW1lc3RhbXAKeHlzIDwtIGNiaW5kKHRpbWVzdGFtcHMsIHh5MSwgeHkyKSAlPiUKICBtdXRhdGVfYWxsKGFzLm51bWVyaWMpICU+JQogIHJvd3dpc2UoKSAlPiUKICBtdXRhdGUoeCA9IG1lYW4oeDEseDIpLAogICAgICAgICB5ID0gbWVhbih5MSwgeTIpKSAlPiUKICBzZWxlY3Qoc2VjLCB4LCB5KQp9CmBgYAoKTGV0J3MgZ2l2ZSB0aGlzIGEgc2hvdCEhCgojIFRocmVlIEJlYXJzIEZvcndhcmQgCkZpcnN0IGxldCdzIHNlZSB3aG8ncyBpbiBvdXIgZGF0YXNldC4gVGhpcyBpcyBUZXN0IDEgLSAzIEJlYXJzIC0gRm9yd2FyZC4gV2UncmUgcHVsbGluZyBjbGVhbmVkLXVwIG5hbWVzIGFuZCBhc3NpZ25lZCBncm91cHMgZnJvbSBvdXIgZmluYWwgZGF0YXNldCB0aGF0IHdlIHVzZWQgaW4gb3VyIEFPSSBhbmFseXNpcy4gVGhlbiB3ZSBhcmUgcmVtb3ZpbmcgcGFydGljaXBhbnRzIHdob3NlIFRocmVlIEJlYXJzIEZvcndhcmQgc3Rvcnkgd2Fzbid0IGluY2x1ZGVkIGluIG91ciBBT0kgYW5hbHlzaXMgZHVlIHRvIDwyNSUgbG9va2luZyB0aW1lIG9yIG90aGVyIHJlYXNvbnMuIAoKYGBge3IgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KbGlicmFyeSh0aWR5dmVyc2UpCmxpYnJhcnkob3Blbnhsc3gpCmxpYnJhcnkoamFuaXRvcikKCiMgR2V0IFRocmVlIEJlYXJzIGRhdGEKZGF0YSA8LSByZWFkLnhsc3goIlRlc3QxX0NpbmR5X2JlYXJzX0ZXX0V4YW1pbmUgZm9yIFNwYXRpYWwgUmVmZXJlbmNpbmcueGxzeCIpICU+JQogIGNsZWFuX25hbWVzKCkgJT4lCiAgcmVuYW1lKHkgPSBnYXplX3BvaW50X3lfbWNfc3B4LAogICAgICAgICBsYW5ndWFnZSA9IGxhbmd1YWdlX3ZhbHVlLAogICAgICAgICBuYW1lID0gcGFydGljaXBhbnRfbmFtZSwKICAgICAgICAgZ3JvdXAgPSBncm91cF92YWx1ZSkKCiMgUHVsbCBjbGVhbiBuYW1lcyBhbmQgam9pbiB0byBkYXRhIChhbmQgYWRkIExhdXJhMiBmb3IgTGF1cmEgKG1pc3Npbmcgc3RvcmllcykpCmNsZWFubmFtZXMgPC0gcmVhZF9jc3YoInBhcnRuYW1lcy5jc3YiKSAlPiUKICBkaXN0aW5jdCgpICU+JQogIHJlbmFtZShuYW1lID0gcGFydGljaXBhbnQpICU+JQogIGZpbHRlcihuYW1lICE9ICJMYXVyYTIiKQoKZGF0YSA8LSBkYXRhICU+JSAKICBsZWZ0X2pvaW4oY2xlYW5uYW1lcywgYnkgPSAibmFtZSIpICU+JQogIHNlbGVjdCgtbmFtZSkgJT4lCiAgcmVuYW1lKG5hbWUgPSBuZXdfcGFydGljaXBhbnQpICU+JQogIGZpbHRlcighaXMubmEobmFtZSkpCgojIFB1bGwgZmluYWwgZ3JvdXAgYXNzaWdubWVudHMgYW5kIGpvaW4gdG8gZGF0YQpjbGVhbmdyb3VwcyA8LSByZWFkX2NzdigiZmluYWxkYXRhc2V0LmNzdiIpICU+JQogIHNlbGVjdChwYXJ0aWNpcGFudCwgbWFpbmdyb3VwKSAlPiUKICByZW5hbWUobmFtZSA9IHBhcnRpY2lwYW50KSAlPiUKICBkaXN0aW5jdCgpCgpkYXRhIDwtIGRhdGEgJT4lIGxlZnRfam9pbihjbGVhbmdyb3VwcywgYnkgPSAibmFtZSIpICU+JQogIHNlbGVjdCgtZ3JvdXApCgojIExldCdzIGZpbmQgb3V0IHdobyB3YXMgTk9UIGluY2x1ZGVkIGluIFRocmVlIEJlYXJzCmV4Y2x1ZGVkIDwtIHJlYWRfY3N2KCJmaW5hbGRhdGFzZXQuY3N2IikgJT4lCiAgc2VsZWN0KHBhcnRpY2lwYW50LCBtYWluZ3JvdXAsIHN0b3J5LCBkaXJlY3Rpb24sIGV5ZV9leGNsdWRlKSAlPiUKICBmaWx0ZXIoc3RvcnkgPT0gIkdvbGRpbG9ja3MiICYgZGlyZWN0aW9uID09ICJmb3J3YXJkIikgJT4lCiAgcmVuYW1lKG5hbWUgPSBwYXJ0aWNpcGFudCkgJT4lCiAgc2VsZWN0KG5hbWUsIGV5ZV9leGNsdWRlKQoKZGF0YSA8LSBkYXRhICU+JSBsZWZ0X2pvaW4oZXhjbHVkZWQsIGJ5ID0gIm5hbWUiKSAlPiUKICBmaWx0ZXIoIWV5ZV9leGNsdWRlKSAlPiUKICBmaWx0ZXIoIWlzLm5hKGV5ZV9leGNsdWRlKSkKCmRhdGEgJT4lIHNlbGVjdChuYW1lLCBtYWluZ3JvdXApICU+JSBkaXN0aW5jdCgpCmBgYAoKTm93IGxldCdzIGdyYXBoISEgCgpNZXNzeSwgSSBrbm93LCBidXQgYWxyZWFkeSB3ZSBjYW4gc2VlIHNvbWUgSGVhcmluZ05vdmljZSBoYXMgYmlnIHNoaWZ0cyBkb3dud2FyZC4gQW5kIHNvbWUgSGVhcmluZ0xhdGUgdG9vLgoKYGBge3J9CmRhdGEgJT4lCiAgZ2dwbG90KGFlcyh4ID0gZ2F6ZV9wb2ludF9pbmRleCwgeSA9IHksIGNvbG9yID0gbWFpbmdyb3VwLCBncm91cCA9IG5hbWUpKSArIGdlb21fbGluZSgpICsgCiAgc2NhbGVfeV9yZXZlcnNlKGxpbWl0cyA9IGMoMTIwMCwwKSkgKwogIHRoZW1lX2J3KCkKYGBgCgojIEdyb3VwIEF2ZXJhZ2VzCgpOZXh0LCBsZXQncyBtYWtlIGdyb3VwIGF2ZXJhZ2VzLiAKCmBgYHtyfQphdmVyYWdlZF95IDwtIGRhdGEgJT4lCiAgZ3JvdXBfYnkobWFpbmdyb3VwLCBnYXplX3BvaW50X2luZGV4KSAlPiUKICBzdW1tYXJpc2UoeV9tZWFuID0gbWVhbih5LCBuYS5ybSA9IFQpLAogICAgICAgICAgICB5X3NkID0gc2QoeSwgbmEucm0gPSBUKSwKICAgICAgICAgICAgeV9jb3VudCA9IG4oKSwKICAgICAgICAgICAgeV9zZSA9IHlfc2Qvc3FydCh5X2NvdW50KSkKCmF2ZXJhZ2VkX3kgJT4lCiAgZ2dwbG90KCkgKyAKICBnZW9tX2xpbmUoYWVzKHggPSBnYXplX3BvaW50X2luZGV4LCB5ID0geV9tZWFuLCBjb2xvciA9IG1haW5ncm91cCkpICsKICBnZW9tX3JpYmJvbihhZXMoeCA9IGdhemVfcG9pbnRfaW5kZXgsIAogICAgICAgICAgICAgICAgICB5bWluID0geV9tZWFuLXlfc2UsIAogICAgICAgICAgICAgICAgICB5bWF4ID0geV9tZWFuK3lfc2UsCiAgICAgICAgICAgICAgICAgIGZpbGwgPSBtYWluZ3JvdXApLCBhbHBoYSA9IDAuNSkgKwogIHNjYWxlX3lfcmV2ZXJzZShsaW1pdHMgPSBjKDEyMDAsMCkpICsKICB0aGVtZV9idygpICsKICBmYWNldF93cmFwKCJtYWluZ3JvdXAiKQoKYXZlcmFnZWRfeSAlPiUKICBnZ3Bsb3QoKSArIAogIGdlb21fbGluZShhZXMoeCA9IGdhemVfcG9pbnRfaW5kZXgsIHkgPSB5X21lYW4sIGNvbG9yID0gbWFpbmdyb3VwKSkgKwogIGdlb21fcmliYm9uKGFlcyh4ID0gZ2F6ZV9wb2ludF9pbmRleCwgCiAgICAgICAgICAgICAgICAgIHltaW4gPSB5X21lYW4teV9zZSwgCiAgICAgICAgICAgICAgICAgIHltYXggPSB5X21lYW4reV9zZSwKICAgICAgICAgICAgICAgICAgZmlsbCA9IG1haW5ncm91cCksIGFscGhhID0gMC41KSArCiAgc2NhbGVfeV9yZXZlcnNlKGxpbWl0cyA9IGMoMTIwMCwwKSkgKwogIHRoZW1lX2J3KCkKYGBgCgojIEdyb3VwIEF2ZXJhZ2VzIFdpdGggU21vb3RoaW5nCgpTbyBJJ2xsIGJhY2sgdXAgYW5kIHNtb290aCBlYWNoIHBlcnNvbidzIGRhdGEgdXNpbmcgYSBtb3ZpbmcgYXZlcmFnZSB3aW5kb3cgb2Ygc3BhbiA9IDUuIFRha2VuIGZyb20gb3VyIGFkdWx0IG1hbnVzY3JpcHQgd2hpY2ggaGFkIHRoaXM6IAoKPiBUaGUgZGF0YSB3ZXJlIHRoZW4gc21vb3RoZWQgd2l0aCBhIHN0YW5kYXJkIG1vdmluZyBhdmVyYWdlIG5vaXNlIHJlZHVjdGlvbiBhbGdvcml0aG0gKHdpbmRvdyBzaXplID0gNSBzYW1wbGVzKSB3aGljaCBhY3RzIGFzIGEgbG93LXBhc3MgZmlsdGVyIHRoYXQgcmVkdWNlcyB0aGUgaW5mbHVlbmNlIG9mIG1pY3Jvc2FjY2FkZXMsIGJsaW5rcywgYW5kIGxhcmdlIGRhdGEgZ2FwcyAoYmFzZWQgb24gWWFyYnVzLCAxOTY3KS4gCgpUaGUgYmVsb3cgY2hhcnQgc2hvd3MgQWRhbSdzIGRhdGEsIGJsdWUgaXMgdW5zbW9vdGhlZCBhbmQgcmVkIGlzIHNtb290aGVkLiAKCgpgYGB7cn0KZGF0YSA8LSBkYXRhICU+JQogIGdyb3VwX2J5KG1haW5ncm91cCwgcmVjb3JkaW5nX25hbWUpICU+JQogIG11dGF0ZSh5X21hID0gUmNwcFJvbGw6OnJvbGxfbWVhbih5LCBuID0gNSwgZmlsbCA9IDApKQoKZGF0YSAlPiUKICBmaWx0ZXIocmVjb3JkaW5nX25hbWUgPT0gIkFkYW1fR29vZCIpICU+JQogIGdncGxvdCgpICsKICBnZW9tX2xpbmUoYWVzKHggPSBnYXplX3BvaW50X2luZGV4LCB5ID0geSksIGNvbG9yID0gImJsdWUiLCBhbHBoYSA9IDAuMjUsIHNpemUgPSAwLjUpICsKICBnZW9tX2xpbmUoYWVzKHggPSBnYXplX3BvaW50X2luZGV4LCB5ID0geV9tYSksIGNvbG9yID0gInJlZCIsIHNpemUgPSAwLjIpICsKICBzY2FsZV95X3JldmVyc2UobGltaXRzID0gYyg0NzUsIDMyNSkpICsKICB0aGVtZV9idygpCmBgYAoKU28gdGhhdCdzIG5pY2UuIExldCdzIGdvIGRvIGdyb3VwIGF2ZXJhZ2VzIGFnYWluLiAKCmBgYHtyfQphdmVyYWdlZF95IDwtIGRhdGEgJT4lCiAgZ3JvdXBfYnkobWFpbmdyb3VwLCBnYXplX3BvaW50X2luZGV4KSAlPiUKICBzdW1tYXJpc2UoeV9tZWFuID0gbWVhbih5X21hLCBuYS5ybSA9IFQpLAogICAgICAgICAgICB5X3NkID0gc2QoeV9tYSwgbmEucm0gPSBUKSwKICAgICAgICAgICAgeV9jb3VudCA9IG4oKSwKICAgICAgICAgICAgeV9zZSA9IHlfc2Qvc3FydCh5X2NvdW50KSkKCmF2ZXJhZ2VkX3kgJT4lCiAgZ2dwbG90KCkgKyAKICBnZW9tX2xpbmUoYWVzKHggPSBnYXplX3BvaW50X2luZGV4LCB5ID0geV9tZWFuLCBjb2xvciA9IG1haW5ncm91cCkpICsKICBnZW9tX3JpYmJvbihhZXMoeCA9IGdhemVfcG9pbnRfaW5kZXgsIAogICAgICAgICAgICAgICAgICB5bWluID0geV9tZWFuLXlfc2UsIAogICAgICAgICAgICAgICAgICB5bWF4ID0geV9tZWFuK3lfc2UsCiAgICAgICAgICAgICAgICAgIGZpbGwgPSBtYWluZ3JvdXApLCBhbHBoYSA9IDAuNSkgKwogIHNjYWxlX3lfcmV2ZXJzZShsaW1pdHMgPSBjKDEyMDAsMCkpICsKICB0aGVtZV9idygpICsKICBmYWNldF93cmFwKCJtYWluZ3JvdXAiKQoKYXZlcmFnZWRfeSAlPiUKICBnZ3Bsb3QoKSArIAogIGdlb21fbGluZShhZXMoeCA9IGdhemVfcG9pbnRfaW5kZXgsIHkgPSB5X21lYW4sIGNvbG9yID0gbWFpbmdyb3VwKSkgKwogIGdlb21fcmliYm9uKGFlcyh4ID0gZ2F6ZV9wb2ludF9pbmRleCwgCiAgICAgICAgICAgICAgICAgIHltaW4gPSB5X21lYW4teV9zZSwgCiAgICAgICAgICAgICAgICAgIHltYXggPSB5X21lYW4reV9zZSwKICAgICAgICAgICAgICAgICAgZmlsbCA9IG1haW5ncm91cCksIGFscGhhID0gMC41KSArCiAgc2NhbGVfeV9yZXZlcnNlKGxpbWl0cyA9IGMoMTIwMCwwKSkgKwogIHRoZW1lX2J3KCkKCmF2ZXJhZ2VkX3kgJT4lCiAgZmlsdGVyKG1haW5ncm91cCA9PSAiRGVhZkVhcmx5IiB8IG1haW5ncm91cCA9PSAiSGVhcmluZ05vdmljZSIpICU+JQogIGdncGxvdCgpICsgCiAgZ2VvbV9saW5lKGFlcyh4ID0gZ2F6ZV9wb2ludF9pbmRleCwgeSA9IHlfbWVhbiwgY29sb3IgPSBtYWluZ3JvdXApKSArCiAgZ2VvbV9yaWJib24oYWVzKHggPSBnYXplX3BvaW50X2luZGV4LCAKICAgICAgICAgICAgICAgICAgeW1pbiA9IHlfbWVhbi15X3NlLCAKICAgICAgICAgICAgICAgICAgeW1heCA9IHlfbWVhbit5X3NlLAogICAgICAgICAgICAgICAgICBmaWxsID0gbWFpbmdyb3VwKSwgYWxwaGEgPSAwLjUpICsKICBzY2FsZV95X3JldmVyc2UobGltaXRzID0gYyg3MDAsMzAwKSkgKwogIHRoZW1lX2J3KCkKYGBgCgojIEdyb3VwIEF2ZXJhZ2VzIFdpdGggTW9yZSBTbW9vdGhpbmcKCk1heWJlIHdlIHNob3VsZCBzbW9vdGggZXZlbiBtb3JlLiBTYW1wbGUgc2l6ZSA9IDEwISAKCmBgYHtyfQpkYXRhIDwtIGRhdGEgJT4lCiAgZ3JvdXBfYnkobWFpbmdyb3VwLCByZWNvcmRpbmdfbmFtZSkgJT4lCiAgbXV0YXRlKHlfbWEyID0gUmNwcFJvbGw6OnJvbGxfbWVhbih5LCBuID0gMTAsIGZpbGwgPSAwKSkKCiMgZGF0YSAlPiUKIyAgIGZpbHRlcihyZWNvcmRpbmdfbmFtZSA9PSAiQWRhbV9Hb29kIikgJT4lCiMgICBnZ3Bsb3QoKSArCiMgICBnZW9tX2xpbmUoYWVzKHggPSBnYXplX3BvaW50X2luZGV4LCB5ID0geSksIGNvbG9yID0gImJsdWUiLCBhbHBoYSA9IDAuMjUsIHNpemUgPSAwLjUpICsKIyAgIGdlb21fbGluZShhZXMoeCA9IGdhemVfcG9pbnRfaW5kZXgsIHkgPSB5X21hMiksIGNvbG9yID0gInJlZCIsIHNpemUgPSAwLjIpICsKIyAgIHNjYWxlX3lfcmV2ZXJzZShsaW1pdHMgPSBjKDQ3NSwgMzI1KSkgKwojICAgdGhlbWVfYncoKQoKYXZlcmFnZWRfeSA8LSBkYXRhICU+JQogIGdyb3VwX2J5KG1haW5ncm91cCwgZ2F6ZV9wb2ludF9pbmRleCkgJT4lCiAgc3VtbWFyaXNlKHlfbWVhbiA9IG1lYW4oeV9tYTIsIG5hLnJtID0gVCksCiAgICAgICAgICAgIHlfc2QgPSBzZCh5X21hMiwgbmEucm0gPSBUKSwKICAgICAgICAgICAgeV9jb3VudCA9IG4oKSwKICAgICAgICAgICAgeV9zZSA9IHlfc2Qvc3FydCh5X2NvdW50KSkKCndyaXRlX2NzdihhdmVyYWdlZF95LCAiYmVhcnNfdGltZV9zZXJpZXNfZ3JvdXBfYXZlcmFnZXMuY3N2IikKCmxpYnJhcnkoaHJicnRoZW1lcykKYXZlcmFnZWRfeSAlPiUKICBnZ3Bsb3QoKSArIAogIGdlb21fbGluZShhZXMoeCA9IGdhemVfcG9pbnRfaW5kZXgsIHkgPSB5X21lYW4sIGNvbG9yID0gbWFpbmdyb3VwKSwgc2l6ZSA9IDAuOCkgKwogIGdlb21fcmliYm9uKGFlcyh4ID0gZ2F6ZV9wb2ludF9pbmRleCwgCiAgICAgICAgICAgICAgICAgIHltaW4gPSB5X21lYW4teV9zZSwgCiAgICAgICAgICAgICAgICAgIHltYXggPSB5X21lYW4reV9zZSwKICAgICAgICAgICAgICAgICAgZmlsbCA9IG1haW5ncm91cCksIGFscGhhID0gMC41KSArCiAgc2NhbGVfeV9yZXZlcnNlKGxpbWl0cyA9IGMoMTIwMCwwKSkgKwogIGZhY2V0X3dyYXAoIm1haW5ncm91cCIpICsKICBsYWJzKHggPSAidGltZSAobXMpIiwgeSA9ICJwaXhlbHMiLCB0aXRsZSA9ICJGaWd1cmUgMS4gVmVydGljYWwgRXllIEdhemUgUG9zaXRpb24gQWNyb3NzIE9uZSBBU0wgTmFycmF0aXZlIikgKwogIGd1aWRlcyhjb2xvciA9IEYsIGZpbGwgPSBGKSArCiAgdGhlbWVfaXBzdW1fcmMoKQoKYXZlcmFnZWRfeSAlPiUKICBnZ3Bsb3QoKSArIAogIGdlb21fbGluZShhZXMoeCA9IGdhemVfcG9pbnRfaW5kZXgsIHkgPSB5X21lYW4sIGNvbG9yID0gbWFpbmdyb3VwKSkgKwogIGdlb21fcmliYm9uKGFlcyh4ID0gZ2F6ZV9wb2ludF9pbmRleCwgCiAgICAgICAgICAgICAgICAgIHltaW4gPSB5X21lYW4teV9zZSwgCiAgICAgICAgICAgICAgICAgIHltYXggPSB5X21lYW4reV9zZSwKICAgICAgICAgICAgICAgICAgZmlsbCA9IG1haW5ncm91cCksIGFscGhhID0gMC41KSArCiAgc2NhbGVfeV9yZXZlcnNlKGxpbWl0cyA9IGMoMTIwMCwwKSkgKwogIHRoZW1lX2J3KCkKCmF2ZXJhZ2VkX3kgJT4lCiAgZmlsdGVyKG1haW5ncm91cCA9PSAiRGVhZkVhcmx5IiB8IG1haW5ncm91cCA9PSAiSGVhcmluZ05vdmljZSIpICU+JQogIGdncGxvdCgpICsgCiAgZ2VvbV9saW5lKGFlcyh4ID0gZ2F6ZV9wb2ludF9pbmRleCwgeSA9IHlfbWVhbiwgY29sb3IgPSBtYWluZ3JvdXApLCBzaXplID0gMC44KSArCiAgZ2VvbV9yaWJib24oYWVzKHggPSBnYXplX3BvaW50X2luZGV4LCAKICAgICAgICAgICAgICAgICAgeW1pbiA9IHlfbWVhbi15X3NlLCAKICAgICAgICAgICAgICAgICAgeW1heCA9IHlfbWVhbit5X3NlLAogICAgICAgICAgICAgICAgICBmaWxsID0gbWFpbmdyb3VwKSwgYWxwaGEgPSAwLjEpICsKICBzY2FsZV95X3JldmVyc2UobGltaXRzID0gYyg3MDAsMzAwKSkgKwogIGxhYnMoeCA9ICJ0aW1lIChtcykiLCB5ID0gInBpeGVscyIsIHRpdGxlID0gIkZpZ3VyZSAyLiBEZWFmIEVhcmx5IFNpZ25lcnMgdnMuIEhlYXJpbmcgTm92aWNlIFNpZ25lcnMiLCBjb2xvciA9ICIiLCBmaWxsID0gIiIpICsKICB0aGVtZV9pcHN1bV9yYygpCgpgYGAKCiMgRXZlcnl0aGluZyBFbHNlIFRoYXQgV2FzIEFscmVhZHkgSGVyZQoKTmV4dCBsZXQncyBwbG90IHRoZSBtb21lbnRzIHdoZXJlIHNwYXRpYWwgcmVmZXJlbmNpbmcgaGFwcGVucy4gVGhvc2UgYXJlIGZyYW1lcwoKMS4gMTk4IHRvIDIyMwoxLiAyNjUgdG8gMjg4CjEuIDM1MiB0byAzODAKClRoZSBtYXggZ2F6ZXBvaW50aW5kZXggaXMgYXJvdW5kIDI1ODAuIEF0IDEyMCBIeiwgdGhhdCdzIDIxLjUgc2Vjb25kcyB3aGljaCBpcyBqdXN0IHJpZ2h0LCB0aGF0J3MgdGhlIGxlbmd0aC4gTGV0J3MgZ28gYWhlYWQgYW5kIGNvbnZlcnQgZ2F6ZXBvaW50aW5kZXggdG8gc2Vjb25kcy4gIAoKU28gd2UganVzdCBoYXZlIHRvIGNvbnZlcnQgZnJhbWVzIHRvIGdhemVwb2ludGluZGV4LiBUaGUgdmlkZW8gaXMgYSB0b3RhbCBvZiA1MzYgZnJhbWVzLCBhdCAyNSBGUFMgdGhhdCdzIDIxLjUgc2Vjb25kcy4gNTM1LzI1ID0gMjEuNSwgc28gd2UgZGl2aWRlIGFsbCB0aG9zZSBmcmFtZXMgYnkgMjUuIAoKMS4gNy45MnMgdG8gOC45MnMKMS4gMTAuNnMgdG8gMTEuNTJzCjEuIDE0LjA4cyB0byAxNS4ycyAKCkFuZCBwbG90IHRob3NlIQoKYGBge3J9CmRhdGEgPC0gZGF0YSAlPiUKICByb3d3aXNlKCkgJT4lCiAgbXV0YXRlKHNlY3MgPSBnYXplX3BvaW50X2luZGV4LzEyMCkKCmRhdGEgJT4lCiAgZ2dwbG90KGFlcyh4ID0gc2VjcywgeSA9IHksIGNvbG9yID0gbWFpbmdyb3VwLCBncm91cCA9IG5hbWUpKSArIAogIHNjYWxlX3lfcmV2ZXJzZSgpICsgCiAgZ2VvbV9saW5lKCkgKyAKICBhbm5vdGF0ZSgicmVjdCIsIHhtaW4gPSA3LjkyLCB4bWF4ID0gOC45MiwgeW1pbiA9IDAsIHltYXggPSA5MDAsCiAgYWxwaGEgPSAuMiwgZmlsbCA9ICJyZWQiKSArCiAgYW5ub3RhdGUoInJlY3QiLCB4bWluID0gMTAuNiwgeG1heCA9IDExLjUyLCB5bWluID0gMCwgeW1heCA9IDkwMCwKICBhbHBoYSA9IC4yLCBmaWxsID0gInJlZCIpICsKICBhbm5vdGF0ZSgicmVjdCIsIHhtaW4gPSAxNC4wOCwgeG1heCA9IDE1LjIsIHltaW4gPSAwLCB5bWF4ID0gOTAwLAogIGFscGhhID0gLjIsIGZpbGwgPSAicmVkIikgKwogIHRoZW1lX2J3KCkKYGBgCgpNYXliZSBlYXNpZXIgaWYgd2Ugc2VwYXJhdGUgZ3JvdXBzIG9mIHNpZ25lcnMuIAoKYGBge3J9CmRhdGEgJT4lCiAgZ2dwbG90KGFlcyh4ID0gc2VjcywgeSA9IHksIGNvbG9yID0gbWFpbmdyb3VwLCBncm91cCA9IG5hbWUpKSArIAogIHNjYWxlX3lfcmV2ZXJzZSgpICsgCiAgZ2VvbV9saW5lKGFscGhhID0gMC41KSArIAogIGFubm90YXRlKCJyZWN0IiwgeG1pbiA9IDcuOTIsIHhtYXggPSA4LjkyLCB5bWluID0gMCwgeW1heCA9IDkwMCwKICBhbHBoYSA9IC4yLCBmaWxsID0gInJlZCIpICsKICBhbm5vdGF0ZSgicmVjdCIsIHhtaW4gPSAxMC42LCB4bWF4ID0gMTEuNTIsIHltaW4gPSAwLCB5bWF4ID0gOTAwLAogIGFscGhhID0gLjIsIGZpbGwgPSAicmVkIikgKwogIGFubm90YXRlKCJyZWN0IiwgeG1pbiA9IDE0LjA4LCB4bWF4ID0gMTUuMiwgeW1pbiA9IDAsIHltYXggPSA5MDAsCiAgYWxwaGEgPSAuMiwgZmlsbCA9ICJyZWQiKSArCiAgZmFjZXRfZ3JpZChtYWluZ3JvdXAgfiAuKSArCiAgdGhlbWVfYncoKSArCiAgZ3VpZGVzKGNvbG9yID0gRkFMU0UpCmBgYAoKTmV4dCwgd2UncmUgZ29pbmcgdG8gYWRkIEFPSSBwb3NpdGlvbiBpbmZvcm1hdGlvbi4gV2UncmUgZ29pbmcgdG8gcHVsbCBpbiBpbmZvcm1hdGlvbiBvbiBzaWduZXJzJyByaWdodCBoYW5kIHBvc2l0aW9uIChhbmQgdGhlbiBhcHBseSB0aGUgc2FtZSBpZGVhIHRvIG90aGVyIGJvZHkgcGFydHMpLiBJIHN1Y2Nlc3NmdWxseSB3cm90ZSBhIGZ1bmN0aW9uIGNhbGxlZCBgZ2V0X3h5X3RpbWVzdGFtcGAgdG8gZG8gdGhpcyEgWWF5LiBJJ20gY2h1ZmZlZCwgYXMgdGhlIEJyaXRpc2ggd291bGQgc2F5LgoKTGV0J3MgdHJ5IHRoaXMgb24gU3RlcGhhbmllJ3MgZGF0YS4gTGV0J3Mgc2VlIGlmIHdlIGNhbiBmaW5kIGEgY29ycmVsYXRpb24gYmV0d2VlbiBhbnkgb2YgdGhvc2UgYW5kIHRoZSBleWUgZ2F6ZSB5LXBvc2l0aW9uLiAKCmBgYHtyfQoKIyBXZSBhZGQgb25lIG1vcmUgcm93IHRvIHRoZSB4eV90aW1lc3RhbXAgZGF0YSB0byBhbGlnbiBpdCB3aXRoIHRoZSBlbmQgb2YgdGhlIGV5ZSBnYXplIGRhdGEuCnJoYW5kIDwtIGdldF94eV90aW1lc3RhbXAoImFvaV9wb3NpdGlvbi9DaW5keV9iZWFyc19GV19Qb3NpdGlvbiBvZiBSaWdodCBIYW5kLnR4dCIpICU+JQogIGFkZF9yb3coc2VjID0gMjEuNSwgeCA9IDY0MC4xNiwgeSA9IDEwNTUuOTcpCmxoYW5kIDwtIGdldF94eV90aW1lc3RhbXAoImFvaV9wb3NpdGlvbi9DaW5keV9iZWFyc19GV19Qb3NpdGlvbiBvZiBMZWZ0IEhhbmQudHh0IikgJT4lCiAgYWRkX3JvdyhzZWMgPSAyMS41LCB4ID0gNzAzLjc0LCB5ID0gMTA1OC4zOSkKbW91dGggPC0gZ2V0X3h5X3RpbWVzdGFtcCgiYW9pX3Bvc2l0aW9uL0NpbmR5X2JlYXJzX0ZXX1Bvc2l0aW9uIG9mIG1vdXRoIHNtYWxsLnR4dCIpICU+JQogIGFkZF9yb3coc2VjID0gMjEuNSwgeCA9IDY1Ni4zNywgeSA9IDM3My45OSkKCiMgR2V0IFN0ZXBoYW5pZSdzIGRhdGEKc3RlcGggPC0gZmlsdGVyKGRhdGEsIG5hbWUgPT0gIlN0ZXBoYW5pZSIpCgpzdGVwaCAlPiUKICBnZ3Bsb3QoYWVzKHggPSBzZWNzLCB5ID0geSkpICsgCiAgc2NhbGVfeV9yZXZlcnNlKGxpbWl0cyA9IGMoMTIwMCwwKSwgZXhwYW5kID0gYygwLDApKSArIAogIGdlb21fbGluZShhbHBoYSA9IDEsIGNvbG9yID0gInB1cnBsZSIpICsgCiAgIyBhbm5vdGF0ZSgicmVjdCIsIHhtaW4gPSA3LjkyLCB4bWF4ID0gOC45MiwgeW1pbiA9IDAsIHltYXggPSAxMjAwLAogICMgYWxwaGEgPSAuMiwgZmlsbCA9ICJyZWQiKSArCiAgIyBhbm5vdGF0ZSgicmVjdCIsIHhtaW4gPSAxMC42LCB4bWF4ID0gMTEuNTIsIHltaW4gPSAwLCB5bWF4ID0gMTIwMCwKICAjIGFscGhhID0gLjIsIGZpbGwgPSAicmVkIikgKwogICMgYW5ub3RhdGUoInJlY3QiLCB4bWluID0gMTQuMDgsIHhtYXggPSAxNS4yLCB5bWluID0gMCwgeW1heCA9IDEyMDAsCiAgIyBhbHBoYSA9IC4yLCBmaWxsID0gInJlZCIpICsKICAjIGdlb21fc3RlcChkYXRhID0gcmhhbmQsIGFlcyh4ID0gc2VjLCB5ID0geSksIGNvbG9yID0gInJlZCIsIGxpbmV0eXBlID0gImxvbmdkYXNoIiwgYWxwaGEgPSAwLjUpICsgCiAgIyBnZW9tX3N0ZXAoZGF0YSA9IGxoYW5kLCBhZXMoeCA9IHNlYywgeSA9IHkpLCBjb2xvciA9ICJibHVlIiwgbGluZXR5cGUgPSAibG9uZ2Rhc2giLCBhbHBoYSA9IDAuNSkgKyAKICAjIGdlb21fc3RlcChkYXRhID0gbW91dGgsIGFlcyh4ID0gc2VjLCB5ID0geSksIGNvbG9yID0gImJsYWNrIiwgbGluZXR5cGUgPSAibG9uZ2Rhc2giLCBhbHBoYSA9IDAuNSkgKyAKICAjIGFubm90YXRlKCJ0ZXh0IiwgbGFiZWwgPSAiUmlnaHQgSGFuZCIsIHggPSAzLCB5ID0gMTAwMCwgY29sb3IgPSAicmVkIiwgYWxwaGEgPSAwLjUpICsKICAjIGFubm90YXRlKCJ0ZXh0IiwgbGFiZWwgPSAiTGVmdCBIYW5kIiwgeCA9IDMsIHkgPSAxMTAwLCBjb2xvciA9ICJibHVlIiwgYWxwaGEgPSAwLjUpICsKICAjIGFubm90YXRlKCJ0ZXh0IiwgbGFiZWwgPSAiTW91dGgiLCB4ID0gMywgeSA9IDIwMCwgY29sb3IgPSAiYmxhY2siLCBhbHBoYSA9IDAuNSkgKwogIGdndGl0bGUoIlN0ZXBoYW5pZSIpICsKICB0aGVtZV9idygpICsKICB0aGVtZShwYW5lbC5ncmlkLm1pbm9yLnkgPSBlbGVtZW50X2JsYW5rKCkpCgpzdGVwaCAlPiUKICBnZ3Bsb3QoYWVzKHggPSBzZWNzLCB5ID0geSkpICsgCiAgc2NhbGVfeV9yZXZlcnNlKGxpbWl0cyA9IGMoMTIwMCwwKSwgZXhwYW5kID0gYygwLDApKSArIAogIGdlb21fbGluZShhbHBoYSA9IDEsIGNvbG9yID0gInB1cnBsZSIpICsgCiAgIyBhbm5vdGF0ZSgicmVjdCIsIHhtaW4gPSA3LjkyLCB4bWF4ID0gOC45MiwgeW1pbiA9IDAsIHltYXggPSAxMjAwLAogICMgYWxwaGEgPSAuMiwgZmlsbCA9ICJyZWQiKSArCiAgIyBhbm5vdGF0ZSgicmVjdCIsIHhtaW4gPSAxMC42LCB4bWF4ID0gMTEuNTIsIHltaW4gPSAwLCB5bWF4ID0gMTIwMCwKICAjIGFscGhhID0gLjIsIGZpbGwgPSAicmVkIikgKwogICMgYW5ub3RhdGUoInJlY3QiLCB4bWluID0gMTQuMDgsIHhtYXggPSAxNS4yLCB5bWluID0gMCwgeW1heCA9IDEyMDAsCiAgIyBhbHBoYSA9IC4yLCBmaWxsID0gInJlZCIpICsKIyAgZ2VvbV9zdGVwKGRhdGEgPSByaGFuZCwgYWVzKHggPSBzZWMsIHkgPSB5KSwgY29sb3IgPSAicmVkIiwgbGluZXR5cGUgPSAibG9uZ2Rhc2giLCBhbHBoYSA9IDAuNSkgKyAKIyAgZ2VvbV9zdGVwKGRhdGEgPSBsaGFuZCwgYWVzKHggPSBzZWMsIHkgPSB5KSwgY29sb3IgPSAiYmx1ZSIsIGxpbmV0eXBlID0gImxvbmdkYXNoIiwgYWxwaGEgPSAwLjUpICsgCiAgZ2VvbV9zdGVwKGRhdGEgPSBtb3V0aCwgYWVzKHggPSBzZWMsIHkgPSB5KSwgY29sb3IgPSAiYmxhY2siLCBsaW5ldHlwZSA9ICJsb25nZGFzaCIsIGFscGhhID0gMC41KSArIAojIGFubm90YXRlKCJ0ZXh0IiwgbGFiZWwgPSAiUmlnaHQgSGFuZCIsIHggPSAzLCB5ID0gMTAwMCwgY29sb3IgPSAicmVkIiwgYWxwaGEgPSAwLjUpICsKIyAgYW5ub3RhdGUoInRleHQiLCBsYWJlbCA9ICJMZWZ0IEhhbmQiLCB4ID0gMywgeSA9IDExMDAsIGNvbG9yID0gImJsdWUiLCBhbHBoYSA9IDAuNSkgKwogIGFubm90YXRlKCJ0ZXh0IiwgbGFiZWwgPSAiTW91dGgiLCB4ID0gMywgeSA9IDI1MCwgY29sb3IgPSAiYmxhY2siLCBhbHBoYSA9IDAuNSkgKwogIGdndGl0bGUoIlN0ZXBoYW5pZSIpICsKICB0aGVtZV9idygpICsKICB0aGVtZShwYW5lbC5ncmlkLm1pbm9yLnkgPSBlbGVtZW50X2JsYW5rKCkpCgpzdGVwaCAlPiUKICBnZ3Bsb3QoYWVzKHggPSBzZWNzLCB5ID0geSkpICsgCiAgc2NhbGVfeV9yZXZlcnNlKGxpbWl0cyA9IGMoMTIwMCwwKSwgZXhwYW5kID0gYygwLDApKSArIAogIGdlb21fbGluZShhbHBoYSA9IDEsIGNvbG9yID0gInB1cnBsZSIpICsgCiAgIyBhbm5vdGF0ZSgicmVjdCIsIHhtaW4gPSA3LjkyLCB4bWF4ID0gOC45MiwgeW1pbiA9IDAsIHltYXggPSAxMjAwLAogICMgYWxwaGEgPSAuMiwgZmlsbCA9ICJyZWQiKSArCiAgIyBhbm5vdGF0ZSgicmVjdCIsIHhtaW4gPSAxMC42LCB4bWF4ID0gMTEuNTIsIHltaW4gPSAwLCB5bWF4ID0gMTIwMCwKICAjIGFscGhhID0gLjIsIGZpbGwgPSAicmVkIikgKwogICMgYW5ub3RhdGUoInJlY3QiLCB4bWluID0gMTQuMDgsIHhtYXggPSAxNS4yLCB5bWluID0gMCwgeW1heCA9IDEyMDAsCiAgIyBhbHBoYSA9IC4yLCBmaWxsID0gInJlZCIpICsKICBnZW9tX3N0ZXAoZGF0YSA9IHJoYW5kLCBhZXMoeCA9IHNlYywgeSA9IHkpLCBjb2xvciA9ICJyZWQiLCBsaW5ldHlwZSA9ICJsb25nZGFzaCIsIGFscGhhID0gMC41KSArIAojICBnZW9tX3N0ZXAoZGF0YSA9IGxoYW5kLCBhZXMoeCA9IHNlYywgeSA9IHkpLCBjb2xvciA9ICJibHVlIiwgbGluZXR5cGUgPSAibG9uZ2Rhc2giLCBhbHBoYSA9IDAuNSkgKyAKICBnZW9tX3N0ZXAoZGF0YSA9IG1vdXRoLCBhZXMoeCA9IHNlYywgeSA9IHkpLCBjb2xvciA9ICJibGFjayIsIGxpbmV0eXBlID0gImxvbmdkYXNoIiwgYWxwaGEgPSAwLjUpICsgCiAgYW5ub3RhdGUoInRleHQiLCBsYWJlbCA9ICJSaWdodCBIYW5kIiwgeCA9IDMsIHkgPSAxMDAwLCBjb2xvciA9ICJyZWQiLCBhbHBoYSA9IDAuNSkgKwojICBhbm5vdGF0ZSgidGV4dCIsIGxhYmVsID0gIkxlZnQgSGFuZCIsIHggPSAzLCB5ID0gMTEwMCwgY29sb3IgPSAiYmx1ZSIsIGFscGhhID0gMC41KSArCiAgYW5ub3RhdGUoInRleHQiLCBsYWJlbCA9ICJNb3V0aCIsIHggPSAzLCB5ID0gMjUwLCBjb2xvciA9ICJibGFjayIsIGFscGhhID0gMC41KSArCiAgZ2d0aXRsZSgiU3RlcGhhbmllIikgKwogIHRoZW1lX2J3KCkgKwogIHRoZW1lKHBhbmVsLmdyaWQubWlub3IueSA9IGVsZW1lbnRfYmxhbmsoKSkKCnN0ZXBoICU+JQogIGdncGxvdChhZXMoeCA9IHNlY3MsIHkgPSB5KSkgKyAKICBzY2FsZV95X3JldmVyc2UobGltaXRzID0gYygxMjAwLDApLCBleHBhbmQgPSBjKDAsMCkpICsgCiAgZ2VvbV9saW5lKGFscGhhID0gMSwgY29sb3IgPSAicHVycGxlIikgKyAKICAjIGFubm90YXRlKCJyZWN0IiwgeG1pbiA9IDcuOTIsIHhtYXggPSA4LjkyLCB5bWluID0gMCwgeW1heCA9IDEyMDAsCiAgIyBhbHBoYSA9IC4yLCBmaWxsID0gInJlZCIpICsKICAjIGFubm90YXRlKCJyZWN0IiwgeG1pbiA9IDEwLjYsIHhtYXggPSAxMS41MiwgeW1pbiA9IDAsIHltYXggPSAxMjAwLAogICMgYWxwaGEgPSAuMiwgZmlsbCA9ICJyZWQiKSArCiAgIyBhbm5vdGF0ZSgicmVjdCIsIHhtaW4gPSAxNC4wOCwgeG1heCA9IDE1LjIsIHltaW4gPSAwLCB5bWF4ID0gMTIwMCwKICAjIGFscGhhID0gLjIsIGZpbGwgPSAicmVkIikgKwogIGdlb21fc3RlcChkYXRhID0gcmhhbmQsIGFlcyh4ID0gc2VjLCB5ID0geSksIGNvbG9yID0gInJlZCIsIGxpbmV0eXBlID0gImxvbmdkYXNoIiwgYWxwaGEgPSAwLjUpICsgCiAgZ2VvbV9zdGVwKGRhdGEgPSBsaGFuZCwgYWVzKHggPSBzZWMsIHkgPSB5KSwgY29sb3IgPSAiYmx1ZSIsIGxpbmV0eXBlID0gImxvbmdkYXNoIiwgYWxwaGEgPSAwLjUpICsgCiAgZ2VvbV9zdGVwKGRhdGEgPSBtb3V0aCwgYWVzKHggPSBzZWMsIHkgPSB5KSwgY29sb3IgPSAiYmxhY2siLCBsaW5ldHlwZSA9ICJsb25nZGFzaCIsIGFscGhhID0gMC41KSArIAogIGFubm90YXRlKCJ0ZXh0IiwgbGFiZWwgPSAiUmlnaHQgSGFuZCIsIHggPSAzLCB5ID0gMTAwMCwgY29sb3IgPSAicmVkIiwgYWxwaGEgPSAwLjUpICsKICBhbm5vdGF0ZSgidGV4dCIsIGxhYmVsID0gIkxlZnQgSGFuZCIsIHggPSAzLCB5ID0gMTEwMCwgY29sb3IgPSAiYmx1ZSIsIGFscGhhID0gMC41KSArCiAgYW5ub3RhdGUoInRleHQiLCBsYWJlbCA9ICJNb3V0aCIsIHggPSAzLCB5ID0gMjUwLCBjb2xvciA9ICJibGFjayIsIGFscGhhID0gMC41KSArCiAgZ2d0aXRsZSgiU3RlcGhhbmllIikgKwogIHRoZW1lX2J3KCkgKwogIHRoZW1lKHBhbmVsLmdyaWQubWlub3IueSA9IGVsZW1lbnRfYmxhbmsoKSkKYGBgCgpOb3cgbGV0J3Mgd29yayBvbiBjb3JyZWxhdGlvbnMuIEZpcnN0LCBvdXIgQU9JIHZlY3RvcnMgYXJlIG5vdCB0aGUgc2FtZSBzaXplIGFzIG91ciBleWUgZ2F6ZSB2ZWN0b3JzLCBhbmQgdGhlIHgveSBwb3NpdGlvbiBpcyBpcnJlZ3VsYXJseSBzcGFjZWQgYWNyb3NzIHRpbWUgKGlycmVndWxhcmx5IHNwYWNlZCBrZXkgZnJhbWVzKS4gCmBgYHtyfQojIFRoZSBmb2xsb3dpbmcgY29kZSB3aWxsICJleHBhbmQiIHRoZSByaGFuZCBkYXRhIHZlY3RvcnMgdG8gZml0IHRoZSBsZW5ndGggb2YgU3RlcGhhbmllJ3MgZGF0YSB2ZWN0b3JzLgp0aW1lX2luZGV4IDwtIHN0ZXBoJHNlY3MKY2xvc2VzdCA8LSBmdW5jdGlvbih4KXsKICB3aGljaC5taW4oYWJzKHRpbWVfaW5kZXgteCkpCn0KCmluZGV4X2xvYyA8LSBtYXBfaW50KHJoYW5kJHNlYywgY2xvc2VzdCkKCnJoYW5kIDwtIGNiaW5kKHJoYW5kLCB0aW1lX2luZGV4W2luZGV4X2xvY10pICU+JQogIHNlbGVjdCgtc2VjKSAlPiUKICByZW5hbWUoc2VjID0gInRpbWVfaW5kZXhbaW5kZXhfbG9jXSIpICU+JQogIHNlbGVjdChzZWMsIHgsIHkpCgpyaGFuZF9mdWxsIDwtIHNlbGVjdChzdGVwaCwgc2VjcykgJT4lCiAgcmVuYW1lKHNlYyA9IHNlY3MpICU+JQogIGxlZnRfam9pbihyaGFuZCkgJT4lCiAgZmlsbCh4KSAlPiUKICBmaWxsKHkpICU+JQogIHNsaWNlKDE6KG5yb3coLiktMSkpCgpyaGFuZF9mdWxsIDwtIHJoYW5kX2Z1bGwgJT4lCiAgZmlsdGVyKHNlYyA8IHJoYW5kJHNlY1sxNzJdKSAlPiUKICBmaWx0ZXIoc2VjID49IHJoYW5kJHNlY1syXSkKCnN0ZXBoIDwtIHN0ZXBoICU+JQogIGZpbHRlcihzZWNzIDwgcmhhbmQkc2VjWzE3Ml0pICU+JQogIGZpbHRlcihzZWNzID49IHJoYW5kJHNlY1syXSkKCmEgPC0gcmhhbmRfZnVsbCR5CmEgPC0gYVsxOmxlbmd0aChhKS0xXSAjIFNob3J0ZW4gaXQgYnkgb25lIGVsZW1lbnQKYiA8LSBzdGVwaCR5CgojIFRoZW4gcnVuIGNvcnJlbGF0aW9ucwpjb3IoYSxiLCB1c2UgPSAiY29tcGxldGUub2JzIikgIyBiYXNpYyBjb3JyZWxhdGlvbgp0aGF0IDwtIGNjZihhLGIsIGxhZy5tYXggPSA0MDAsIHR5cGUgPSAiY29ycmVsYXRpb24iLCBuYS5hY3Rpb24gPSBuYS5wYXNzLCBwbG90ID0gVCkgIyBhdXRvLWNvcnJlbGF0aW9uCmBgYAoKCkxldCdzIHNlcGFyYXRlIG91dCBpbmRpdmlkdWFsIHNpZ25lcnMuIAoKYGBge3J9Cm1ha2Vfc2lnbmVyX3Bsb3RzIDwtIGZ1bmN0aW9uKGdyb3VwbmFtZSwgbGluZV9jb2xvcikgewogIGRhdGEgJT4lCiAgZmlsdGVyKG1haW5ncm91cCA9PSBncm91cG5hbWUpICU+JQogIGdncGxvdChhZXMoeCA9IHNlY3MsIHkgPSB5KSkgKyAKICBzY2FsZV95X3JldmVyc2UoKSArIAogIGdlb21fbGluZShhbHBoYSA9IDEsIGNvbG9yID0gbGluZV9jb2xvcikgKyAKICBhbm5vdGF0ZSgicmVjdCIsIHhtaW4gPSA3LjkyLCB4bWF4ID0gOC45MiwgeW1pbiA9IDAsIHltYXggPSA5MDAsCiAgYWxwaGEgPSAuMiwgZmlsbCA9ICJyZWQiKSArCiAgYW5ub3RhdGUoInJlY3QiLCB4bWluID0gMTAuNiwgeG1heCA9IDExLjUyLCB5bWluID0gMCwgeW1heCA9IDkwMCwKICBhbHBoYSA9IC4yLCBmaWxsID0gInJlZCIpICsKICBhbm5vdGF0ZSgicmVjdCIsIHhtaW4gPSAxNC4wOCwgeG1heCA9IDE1LjIsIHltaW4gPSAwLCB5bWF4ID0gOTAwLAogIGFscGhhID0gLjIsIGZpbGwgPSAicmVkIikgKwogIGdlb21fc3RlcChkYXRhID0gcmhhbmQsIGFlcyh4ID0gc2VjLCB5ID0geSksIGNvbG9yID0gInJlZCIsIGxpbmV0eXBlID0gImxvbmdkYXNoIiwgYWxwaGEgPSAwLjUpICsgCiAgZ2VvbV9zdGVwKGRhdGEgPSBsaGFuZCwgYWVzKHggPSBzZWMsIHkgPSB5KSwgY29sb3IgPSAiYmx1ZSIsIGxpbmV0eXBlID0gImxvbmdkYXNoIiwgYWxwaGEgPSAwLjUpICsgCiAgZ2VvbV9zdGVwKGRhdGEgPSBtb3V0aCwgYWVzKHggPSBzZWMsIHkgPSB5KSwgY29sb3IgPSAiYmxhY2siLCBsaW5ldHlwZSA9ICJsb25nZGFzaCIsIGFscGhhID0gMC41KSArIAogIGFubm90YXRlKCJ0ZXh0IiwgbGFiZWwgPSAiUmlnaHQgSGFuZCIsIHggPSAzLCB5ID0gMTAwMCwgY29sb3IgPSAicmVkIiwgYWxwaGEgPSAwLjUpICsKICBhbm5vdGF0ZSgidGV4dCIsIGxhYmVsID0gIkxlZnQgSGFuZCIsIHggPSAzLCB5ID0gMTEwMCwgY29sb3IgPSAiYmx1ZSIsIGFscGhhID0gMC41KSArCiAgYW5ub3RhdGUoInRleHQiLCBsYWJlbCA9ICJNb3V0aCIsIHggPSAzLCB5ID0gMjAwLCBjb2xvciA9ICJibGFjayIsIGFscGhhID0gMC41KSArCiAgZmFjZXRfZ3JpZChuYW1lIH4gLikgKwogIGdndGl0bGUoZ3JvdXBuYW1lKSArCiAgdGhlbWVfYncoKQp9CgptYWtlX3NpZ25lcl9wbG90cygiRGVhZkVhcmx5IiwgInJlZCIpCm1ha2Vfc2lnbmVyX3Bsb3RzKCJEZWFmTGF0ZSIsICJkYXJrIGdyZWVuIikKbWFrZV9zaWduZXJfcGxvdHMoIkhlYXJpbmdMYXRlIiwgImJsdWUiKQptYWtlX3NpZ25lcl9wbG90cygiSGVhcmluZ05vdmljZSIsICJwdXJwbGUiKQpgYGAKCk9rYXkgc28gd2l0aCBFYXJseSBBU0wgb2J2aW91c2x5IHZlcnkgc3RlYWR5IGdhemUuIE5vdmljZUFTTCBoYXMgbG90IG9mIGRvd25zaGlmdHMuIFNvbWUgYWxpZ24gd2l0aCBzcGF0aWFsIHJlZmVyZW5jaW5nLCBzb21lIGRvIG5vdC4gV2UgbmVlZCBtb3JlIG9mIHRoZW0gKGxldCdzIGxvb2sgYXQgb3RoZXIgc3RvcmllcyB3IGJldHRlciBkYXRhKS4gCgoKIyBNaWRhcyBGb3J3YXJkCgpgYGB7ciBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQojIEdldCBNaWRhcyBkYXRhCmRhdGEgPC0gcmVhZF9jc3YoIi4uL0FkdWx0IERhdGEvcmF3ZGF0YS9taWRhc2Z3LmNzdiIpICU+JQogIGNsZWFuX25hbWVzKCkgJT4lCiAgcmVuYW1lKHkgPSBnYXplX3BvaW50X3lfbWNfc3B4LAogICAgICAgICBsYW5ndWFnZSA9IGxhbmd1YWdlX3ZhbHVlLAogICAgICAgICBuYW1lID0gcGFydGljaXBhbnRfbmFtZSwKICAgICAgICAgZ3JvdXAgPSBncm91cF92YWx1ZSkKCiMgUHVsbCBjbGVhbiBuYW1lcyBhbmQgam9pbiB0byBkYXRhCmNsZWFubmFtZXMgPC0gcmVhZF9jc3YoInBhcnRuYW1lcy5jc3YiKSAlPiUKICBkaXN0aW5jdCgpICU+JQogIHJlbmFtZShuYW1lID0gcGFydGljaXBhbnQpCgpkYXRhIDwtIGRhdGEgJT4lIGxlZnRfam9pbihjbGVhbm5hbWVzLCBieSA9ICJuYW1lIikgJT4lCiAgc2VsZWN0KC1uYW1lKSAlPiUKICByZW5hbWUobmFtZSA9IG5ld19wYXJ0aWNpcGFudCkgJT4lCiAgZmlsdGVyKCFpcy5uYShuYW1lKSkKCiMgUHVsbCBmaW5hbCBncm91cCBhc3NpZ25tZW50cyBhbmQgam9pbiB0byBkYXRhCmNsZWFuZ3JvdXBzIDwtIHJlYWRfY3N2KCJmaW5hbGRhdGFzZXQuY3N2IikgJT4lCiAgc2VsZWN0KHBhcnRpY2lwYW50LCBtYWluZ3JvdXApICU+JQogIHJlbmFtZShuYW1lID0gcGFydGljaXBhbnQpICU+JQogIGRpc3RpbmN0KCkKCmRhdGEgPC0gZGF0YSAlPiUgbGVmdF9qb2luKGNsZWFuZ3JvdXBzLCBieSA9ICJuYW1lIikgJT4lCiAgc2VsZWN0KC1ncm91cCkKCiMgTGV0J3MgZmluZCBvdXQgd2hvIHdhcyBOT1QgaW5jbHVkZWQgaW4gVGhyZWUgQmVhcnMKZXhjbHVkZWQgPC0gcmVhZF9jc3YoImZpbmFsZGF0YXNldC5jc3YiKSAlPiUKICBzZWxlY3QocGFydGljaXBhbnQsIG1haW5ncm91cCwgc3RvcnksIGRpcmVjdGlvbiwgZXllX2V4Y2x1ZGUpICU+JQogIGZpbHRlcihzdG9yeSA9PSAiS2luZ01pZGFzIiAmIGRpcmVjdGlvbiA9PSAiZm9yd2FyZCIpICU+JQogIHJlbmFtZShuYW1lID0gcGFydGljaXBhbnQpICU+JQogIHNlbGVjdChuYW1lLCBleWVfZXhjbHVkZSkKCmRhdGEgPC0gZGF0YSAlPiUgbGVmdF9qb2luKGV4Y2x1ZGVkLCBieSA9ICJuYW1lIikgJT4lCiAgZmlsdGVyKCFleWVfZXhjbHVkZSkgJT4lCiAgZmlsdGVyKCFpcy5uYShleWVfZXhjbHVkZSkpCgpkYXRhICU+JSBzZWxlY3QobmFtZSwgbWFpbmdyb3VwKSAlPiUgZGlzdGluY3QoKQpgYGAKCk5vdyBsZXQncyBncmFwaCEhIAoKSG0uIE9uZSBwZXJzb24gc2VlbXMgd3JvbmcuIApgYGB7cn0KZGF0YSAlPiUKICBnZ3Bsb3QoYWVzKHggPSBnYXplX3BvaW50X2luZGV4LCB5ID0geSwgY29sb3IgPSBtYWluZ3JvdXAsIGdyb3VwID0gbmFtZSkpICsgZ2VvbV9saW5lKCkgKyBzY2FsZV95X3JldmVyc2UoKQpgYGAKT2theSBpdCdzIEplc3NlJ3MgZGF0YSB0aGF0IHNlZW1zIG9mZi4gV2UnbGwgcmVtb3ZlIGhpbSBmb3Igbm93IGFuZCBjb21lIGJhY2sgdG8gaXQsIGZpZ3VyZSBvdXQgd2h5LiAKYGBge3J9CmRhdGEgJT4lIGZpbHRlcihnYXplX3BvaW50X2luZGV4ID4gMzAwMDApICU+JSBzZWxlY3QobmFtZSkgJT4lIGRpc3RpbmN0KCkgJT4lIGhlYWQoKQpgYGAKCmBgYHtyfQpkYXRhIDwtIGRhdGEgJT4lCiAgZmlsdGVyKG5hbWUgIT0gIkplc3NlIikKCmRhdGEgJT4lCiAgZ2dwbG90KGFlcyh4ID0gZ2F6ZV9wb2ludF9pbmRleCwgeSA9IHksIGNvbG9yID0gbWFpbmdyb3VwLCBncm91cCA9IG5hbWUpKSArIGdlb21fbGluZSgpICsgCiAgc2NhbGVfeV9yZXZlcnNlKCkgKwogIHNjYWxlX3hfY29udGludW91cyhsaW1pdHMgPSBjKDAsNDUwMCkpCmBgYAoKTmV4dCBsZXQncyBwbG90IHRoZSBtb21lbnRzIHdoZXJlIHNwYXRpYWwgcmVmZXJlbmNpbmcgaGFwcGVucy4gVGhvc2UgYXJlIGZyYW1lcwoKMS4gMjQ4IHRvIDQyNwoxLiA0NjAgdG8gNTA4CjEuIDUxMiB0byA1NjAKCkxpa2UgYmVmb3JlLCB3ZSdsbCBjb252ZXJ0IGdhemVwb2ludGluZGV4IHRvIHNlY29uZHMgKGJ5IGRpdmlkaW5nIDEyMCkgYW5kIGFsbCBmcmFtZXMgdG8gc2Vjb25kcyAoYnkgZGl2aWRpbmcgMjUpLiAKCjEuIDkuOTJzIHRvIDE3LjA4cwoxLiAxOC40cyB0byAyMC4zMnMKMS4gMjAuNDhzIHRvIDIyLjRzIAoKYGBge3J9CmRhdGEgPC0gZGF0YSAlPiUKICByb3d3aXNlKCkgJT4lCiAgbXV0YXRlKHNlY3MgPSBnYXplX3BvaW50X2luZGV4LzEyMCkKCmRhdGEgJT4lCiAgZ2dwbG90KGFlcyh4ID0gc2VjcywgeSA9IHksIGNvbG9yID0gbWFpbmdyb3VwLCBncm91cCA9IG5hbWUpKSArIAogIHNjYWxlX3lfcmV2ZXJzZSgpICsgCiAgc2NhbGVfeF9jb250aW51b3VzKGxpbWl0cyA9IGMoMCwgMzcuNSkpICsKICBnZW9tX2xpbmUoKSArIAogIGFubm90YXRlKCJyZWN0IiwgeG1pbiA9IDkuOTIsIHhtYXggPSAxNy4wOCwgeW1pbiA9IDAsIHltYXggPSA5MDAsCiAgYWxwaGEgPSAuMiwgZmlsbCA9ICJyZWQiKSArCiAgYW5ub3RhdGUoInJlY3QiLCB4bWluID0gMTguNCwgeG1heCA9IDIwLjMyLCB5bWluID0gMCwgeW1heCA9IDkwMCwKICBhbHBoYSA9IC4yLCBmaWxsID0gInJlZCIpICsKICBhbm5vdGF0ZSgicmVjdCIsIHhtaW4gPSAyMC40OCwgeG1heCA9IDIyLjQsIHltaW4gPSAwLCB5bWF4ID0gOTAwLAogIGFscGhhID0gLjIsIGZpbGwgPSAicmVkIikKYGBgCgpNYXliZSBlYXNpZXIgaWYgd2Ugc2VwYXJhdGUgZ3JvdXBzIG9mIHNpZ25lcnMuIAoKYGBge3J9CmRhdGEgJT4lCiAgZ2dwbG90KGFlcyh4ID0gc2VjcywgeSA9IHksIGNvbG9yID0gbWFpbmdyb3VwLCBncm91cCA9IG5hbWUpKSArIAogIHNjYWxlX3lfcmV2ZXJzZSgpICsgCiAgc2NhbGVfeF9jb250aW51b3VzKGxpbWl0cyA9IGMoMCwgMzcuNSkpICsKICBnZW9tX2xpbmUoYWxwaGEgPSAwLjUpICsgCiAgYW5ub3RhdGUoInJlY3QiLCB4bWluID0gOS45MiwgeG1heCA9IDE3LjA4LCB5bWluID0gMCwgeW1heCA9IDkwMCwKICBhbHBoYSA9IC4yLCBmaWxsID0gInJlZCIpICsKICBhbm5vdGF0ZSgicmVjdCIsIHhtaW4gPSAxOC40LCB4bWF4ID0gMjAuMzIsIHltaW4gPSAwLCB5bWF4ID0gOTAwLAogIGFscGhhID0gLjIsIGZpbGwgPSAicmVkIikgKwogIGFubm90YXRlKCJyZWN0IiwgeG1pbiA9IDIwLjQ4LCB4bWF4ID0gMjIuNCwgeW1pbiA9IDAsIHltYXggPSA5MDAsCiAgYWxwaGEgPSAuMiwgZmlsbCA9ICJyZWQiKSArCiAgZmFjZXRfZ3JpZChtYWluZ3JvdXAgfiAuKQpgYGAKCkluZGl2aWR1YWwgc2lnbmVycy4gCgpgYGB7cn0KZGF0YSAlPiUKICBmaWx0ZXIobWFpbmdyb3VwID09ICJEZWFmRWFybHkiKSAlPiUKICBnZ3Bsb3QoYWVzKHggPSBzZWNzLCB5ID0geSwgZ3JvdXAgPSBuYW1lKSkgKyAKICBzY2FsZV94X2NvbnRpbnVvdXMobGltaXRzID0gYygwLCAzNy41KSkgKwogIHNjYWxlX3lfcmV2ZXJzZSgpICsgCiAgZ2VvbV9saW5lKGFscGhhID0gMSwgY29sb3IgPSAicmVkIikgKyAKICBhbm5vdGF0ZSgicmVjdCIsIHhtaW4gPSA5LjkyLCB4bWF4ID0gMTcuMDgsIHltaW4gPSAwLCB5bWF4ID0gOTAwLAogIGFscGhhID0gLjIsIGZpbGwgPSAicmVkIikgKwogIGFubm90YXRlKCJyZWN0IiwgeG1pbiA9IDE4LjQsIHhtYXggPSAyMC4zMiwgeW1pbiA9IDAsIHltYXggPSA5MDAsCiAgYWxwaGEgPSAuMiwgZmlsbCA9ICJyZWQiKSArCiAgYW5ub3RhdGUoInJlY3QiLCB4bWluID0gMjAuNDgsIHhtYXggPSAyMi40LCB5bWluID0gMCwgeW1heCA9IDkwMCwKICBhbHBoYSA9IC4yLCBmaWxsID0gInJlZCIpICsKICBmYWNldF9ncmlkKG5hbWUgfiAuKSArCiAgZ2d0aXRsZSgiRGVhZkVhcmx5IikKCmRhdGEgJT4lCiAgZmlsdGVyKG1haW5ncm91cCA9PSAiRGVhZkxhdGUiKSAlPiUKICBnZ3Bsb3QoYWVzKHggPSBzZWNzLCB5ID0geSwgZ3JvdXAgPSBuYW1lKSkgKyAKICBzY2FsZV95X3JldmVyc2UoKSArIAogIHNjYWxlX3hfY29udGludW91cyhsaW1pdHMgPSBjKDAsIDM3LjUpKSArCiAgZ2VvbV9saW5lKGFscGhhID0gMSwgY29sb3IgPSAiZGFyayBncmVlbiIpICsgCiAgYW5ub3RhdGUoInJlY3QiLCB4bWluID0gOS45MiwgeG1heCA9IDE3LjA4LCB5bWluID0gMCwgeW1heCA9IDkwMCwKICBhbHBoYSA9IC4yLCBmaWxsID0gInJlZCIpICsKICBhbm5vdGF0ZSgicmVjdCIsIHhtaW4gPSAxOC40LCB4bWF4ID0gMjAuMzIsIHltaW4gPSAwLCB5bWF4ID0gOTAwLAogIGFscGhhID0gLjIsIGZpbGwgPSAicmVkIikgKwogIGFubm90YXRlKCJyZWN0IiwgeG1pbiA9IDIwLjQ4LCB4bWF4ID0gMjIuNCwgeW1pbiA9IDAsIHltYXggPSA5MDAsCiAgYWxwaGEgPSAuMiwgZmlsbCA9ICJyZWQiKSArCiAgZmFjZXRfZ3JpZChuYW1lIH4gLikgKwogIGdndGl0bGUoIkRlYWZMYXRlIikKCmRhdGEgJT4lCiAgZmlsdGVyKG1haW5ncm91cCA9PSAiSGVhcmluZ0xhdGUiKSAlPiUKICBnZ3Bsb3QoYWVzKHggPSBzZWNzLCB5ID0geSwgZ3JvdXAgPSBuYW1lKSkgKyAKICBzY2FsZV95X3JldmVyc2UoKSArIAogIHNjYWxlX3hfY29udGludW91cyhsaW1pdHMgPSBjKDAsIDM3LjUpKSArCiAgZ2VvbV9saW5lKGFscGhhID0gMSwgY29sb3IgPSAiYmx1ZSIpICsgCiAgYW5ub3RhdGUoInJlY3QiLCB4bWluID0gOS45MiwgeG1heCA9IDE3LjA4LCB5bWluID0gMCwgeW1heCA9IDkwMCwKICBhbHBoYSA9IC4yLCBmaWxsID0gInJlZCIpICsKICBhbm5vdGF0ZSgicmVjdCIsIHhtaW4gPSAxOC40LCB4bWF4ID0gMjAuMzIsIHltaW4gPSAwLCB5bWF4ID0gOTAwLAogIGFscGhhID0gLjIsIGZpbGwgPSAicmVkIikgKwogIGFubm90YXRlKCJyZWN0IiwgeG1pbiA9IDIwLjQ4LCB4bWF4ID0gMjIuNCwgeW1pbiA9IDAsIHltYXggPSA5MDAsCiAgYWxwaGEgPSAuMiwgZmlsbCA9ICJyZWQiKSArCiAgZmFjZXRfZ3JpZChuYW1lIH4gLikgKwogIGdndGl0bGUoIkhlYXJpbmdMYXRlIikKCmRhdGEgJT4lCiAgZmlsdGVyKG1haW5ncm91cCA9PSAiSGVhcmluZ05vdmljZSIpICU+JQogIGdncGxvdChhZXMoeCA9IHNlY3MsIHkgPSB5LCBncm91cCA9IG5hbWUpKSArIAogIHNjYWxlX3lfcmV2ZXJzZSgpICsgCiAgc2NhbGVfeF9jb250aW51b3VzKGxpbWl0cyA9IGMoMCwgMzcuNSkpICsKICBnZW9tX2xpbmUoYWxwaGEgPSAxLCBjb2xvciA9ICJwdXJwbGUiKSArIAogIGFubm90YXRlKCJyZWN0IiwgeG1pbiA9IDkuOTIsIHhtYXggPSAxNy4wOCwgeW1pbiA9IDAsIHltYXggPSA5MDAsCiAgYWxwaGEgPSAuMiwgZmlsbCA9ICJyZWQiKSArCiAgYW5ub3RhdGUoInJlY3QiLCB4bWluID0gMTguNCwgeG1heCA9IDIwLjMyLCB5bWluID0gMCwgeW1heCA9IDkwMCwKICBhbHBoYSA9IC4yLCBmaWxsID0gInJlZCIpICsKICBhbm5vdGF0ZSgicmVjdCIsIHhtaW4gPSAyMC40OCwgeG1heCA9IDIyLjQsIHltaW4gPSAwLCB5bWF4ID0gOTAwLAogIGFscGhhID0gLjIsIGZpbGwgPSAicmVkIikgKwogIGZhY2V0X2dyaWQobmFtZSB+IC4pICsKICBnZ3RpdGxlKCJIZWFyaW5nTm92aWNlIikKYGBg